/*
 * @Descripttion:utility 函数
 * @Author: tanwei
 * @Date: 2020-07-04 17:35:29
 * @LastEditors: tanwei
 * @LastEditTime: 2020-07-22 17:12:29
 * @FilePath: /egg/admin/app/extend/helper.js
 */
'use strict';
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// const { codeStatus } = require('./constants');
// const NodeRSA = require('node-rsa');
// const CryptoJS = require('crypto-js');
const xlsx = require('node-xlsx');
const moment = require('moment');
const path = require('path');
const fs = require('fs');

module.exports = {
  // 密码加密
  addSaltPassword(pwd) {
    // const { config } = this.app;
    const md5 = crypto.createHash('md5');
    const pwdCrypto = md5.update(pwd).digest('hex');
    return pwdCrypto;
  },
  // 设置登录token
  async loginToken(data, expires) {
    const { config } = this.app;
    const token = jwt.sign(data, config.jwt.secret, {
      expiresIn: expires,
    });
    // const RedisKey = `user:${data.id}`;
    // await this.setRedis(RedisKey, {
    //   token,
    // }, expires);
    return token;
  },

  // 统一处理返回body信息
  render(code, data = {}, message) {
    const { ctx } = this;
    // 把返回的所有数据_链接的转为小驼峰
    this.jsonToHump(data);
    const bodyData = {
      code,
      ...data,
    };
    if (message) {
      bodyData.message = message;
    }
    ctx.body = bodyData;
    ctx.status = code;
    return;
  },
  // json对象的key值_转为小驼峰
  jsonToHump(obj) {
    if (obj instanceof Array) {
      obj.forEach(v => {
        this.jsonToHump(v);
      });
    } else if (obj instanceof Object) {
      Object.keys(obj).forEach(key => {
        const newKey = this._toHump(key);
        if (newKey !== key) {
          obj[newKey] = obj[key];
          delete obj[key];
        }
        this.jsonToHump(obj[newKey]);
      });
    }
  },
  // 字符串的下划线格式转驼峰格式
  _toHump(name) {
    return name.replace(/\_(\w)/g, (all, letter) => letter.toUpperCase());
  },
  // 参数验证返回统一处理
  validatorFormat(arr) {
    const res = arr.map(val => {
      val.code === 'missing_field' && (val.message = '不能为空!');
      val.code === 'invalid' && (val.message = '无效参数或参数格式错误!');
      return {
        field: val.field,
        message: val.message,
      };
    });
    return res;
  },
  // 平铺转树
  toTree(data, pidAttr = 'pid', idAttr = 'id', id = 0, array = []) {
    const newArr = data.filter(item => item[pidAttr] === id);
    newArr.forEach(item => {
      const result = [];
      const children = this.toTree(data, pidAttr, idAttr, item[idAttr], result);
      if (children && children.length > 0) {
        item.children = children;
      }
      delete item[pidAttr];
      array.push(item);
    });
    return array;
  },
  async exportFile({ data, filename, options = [], saveXlsx = false, directoryPath = './' }) {
    // 因为插件问题，如果使用xlsx样式无效，请安装xlsx-style，
    // 并且修改/node_modules/node-xlsx/lib/index.js 中
    // var _xlsx = _interopRequireDefault(require("xlsx")) 改为 var _xlsx = _interopRequireDefault(require('xlsx-style'));
    const { ctx } = this;
    const buffer = xlsx.build(data, options);
    const newFilename = `${encodeURIComponent(filename)} ${moment(Date.now()).format('YYYY-MM-DD')}`;
    // 存储在本地
    if (saveXlsx) {
      const filePath = path.resolve(__dirname, '../public/export/', directoryPath, `${newFilename}.xlsx`);
      fs.writeFileSync(filePath, buffer, 'utf-8');
    }
    // 返回流文件
    ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8');
    ctx.set('Content-disposition', `attachment;filename=${newFilename}.xlsx`);

    // 直接返回二进制，或者读取刚才存储的文件返回也行
    // return fs.createReadStream(filePath, 'base64'); // 读取本地保存的文件返回
    return buffer.toString('base64');
  },
  createSelectSql(dbName, {
    columns = [], where = {}, page = '', page_size = '', field, order,
  }) {
    let sql = `SELECT ${columns.length < 1 ? '*' : columns.toString()} FROM ${dbName}`;
    const wheres = Object.keys(where);
    let whereIndex = 0;
    if (wheres.length >= 1) {
      sql += ' WHERE ';
      for (const key in where) {
        let value = where[key];
        let operator = '=';
        if (Array.isArray(value) === 'array') {
          operator = 'IN';
        } else if (typeof value === 'object') {
          operator = value.op;
          value = value.value;
        }
        sql += key + ` ${operator} ` + value;
        whereIndex++;
        if (whereIndex <= wheres.length - 1) {
          sql += ' AND ';
        }
      }
    }

    if (field) {
      sql += ` ORDER BY ${field} ${order}`;
    }

    if (page && page_size) {
      sql += ` LIMIT ${page_size} OFFSET ${(page - 1) * page_size}`;
    }
    return sql;
  },
};
